/*
 * Copyright 2008-2023 dexian.vip. All rights reserved.
 * Support: http://www.dexian.vip
 * License: http://www.dexian.vip/license
 */

package vip.dexian.core.base.query;

import vip.dexian.common.query.BaseQueryable;
import vip.dexian.common.query.Filter;
import vip.dexian.common.query.LocalDateTimeBetween;
import vip.dexian.common.query.Operator;
import vip.dexian.common.query.Order;
import vip.dexian.common.utils.CollectionUtils;
import vip.dexian.common.utils.FilterUtils;
import vip.dexian.common.utils.LocalDateTimeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.ui.ModelMap;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 客户端搜索参数封装
 *
 * @author 挺好的 2023年06月02日 9:30
 */
public interface BaseSearcher {


    /**
     * 获取搜索条件，该方法由具体的form类自己实现。应用场景适用于表单的高级搜索。
     *
     * @return 搜索条件
     */
    List <Filter> filters ();

    /**
     * 获取排序条件，该方法由具体的form类自己实现
     *
     * @return 排序条件
     */
    List <Order> orders ();

    /**
     * 构造Query对象
     *
     * @return 返回Query对象
     */
    BaseQueryable query ();

    /**
     * 设置到model map 中
     *
     * @param modelMap
     *         模型数据
     */
    void addAttribute (ModelMap modelMap);

    /**
     * 添加创建时间搜索条件以及其他条件
     *
     * @param beginDate
     *         开始时间
     * @param endDate
     *         结束时间
     * @param searchProperty
     *         搜索的属性名称
     * @param searchValue
     *         属性值
     * @param searchPropertyType
     *         使用的连接符
     *
     * @return 搜索条件
     */
    default List <Filter> addFilters (LocalDateTime beginDate, LocalDateTime endDate, String searchProperty,
            String searchValue, Operator searchPropertyType) {

        List <Filter> filters = CollectionUtils.emptyIfNull(this.filters());

        if (StringUtils.isNotEmpty(searchProperty) && StringUtils.isNotEmpty(searchValue)) {

            if (searchPropertyType == null) {
                filters.add(Filter.like(searchProperty, searchValue));
            } else {
                // TODO 剩余的Operator需要补充
                switch (searchPropertyType) {
                    case RIGHT_LIKE -> filters.add(Filter.likeRight(searchProperty, searchValue));
                }
            }
        }

        // 开始时间大于结束时间
        if (!LocalDateTimeUtils.isAfter(beginDate, endDate)) {
            LocalDateTimeBetween localDateTimeBetween = LocalDateTimeBetween.of(beginDate, endDate);
            filters.add(Filter.between(FilterUtils.CREATE_DATE_PROPERTY_NAME, localDateTimeBetween));
        }

        return filters;
    }

    /**
     * 添加创建时间搜索条件以及其他条件
     *
     * @param beginDate
     *         开始时间
     * @param endDate
     *         结束时间
     * @param filters
     *         搜索条件
     *
     * @return 搜索条件
     */
    default void addFilters (LocalDateTime beginDate, LocalDateTime endDate, List <Filter> filters) {
        LocalDateTimeBetween localDateTimeBetween = LocalDateTimeBetween.of(beginDate, endDate, true);
        if (localDateTimeBetween.isValid()) {
            filters.add(Filter.between(FilterUtils.CREATE_DATE_PROPERTY_NAME, localDateTimeBetween));
        }
    }

    /**
     * 添加客户端的排序
     *
     * @param orderProperty
     *         排序的属性名称
     * @param direction
     *         升序还是降序
     *
     * @return 排序条件
     */
    default List <Order> addOrders (String orderProperty, Order.Direction direction) {

        List <Order> orders = CollectionUtils.emptyIfNull(this.orders());

        if (StringUtils.isEmpty(orderProperty) || direction == null) {
            return orders;
        }

        orders.add(new Order(orderProperty, direction));

        return orders;
    }
}
